﻿using System;
using YasharEl.Infrastructure.ApplicationModel.Bootstrap.Extensibility;
using System.Diagnostics.Contracts;

namespace YasharEl.Infrastructure.ApplicationModel.Bootstrap
{
    public interface IBootstrapper
    {
        /// <summary>
        /// Runs the bootstrapper.
        /// </summary>
        /// <exception cref="BootstrapperException">When an exception occurred during bootstrapping.</exception>
        void Run();

        /// <summary>
        /// Shutdowns the bootstrapper.
        /// </summary>
        /// <exception cref="BootstrapperException">When an exception occurred during bootstrapping.</exception>
        void Shutdown();

        #region Events

        event EventHandler Started;

        #endregion
    }

    [ContractClass(typeof(BootstrapperContract<>))]
    public interface IBootstrapper<TExtension> : IBootstrapper, IBootstrappingExtensionPoint<TExtension>, IDisposable
        where TExtension : IBootstrappingExtension
    {
        #region Methods

        /// <summary>
        /// Initializes the bootstrapper with the bootsrapping strategy.
        /// </summary>
        /// <param name="strategy">The strategy.</param>
        void Initialize(IBootstrappingStrategy<TExtension> strategy);

        #endregion
    }

    [ContractClassFor(typeof(IBootstrapper<>))]
    internal abstract class BootstrapperContract<TExtension> : IBootstrapper<TExtension>
        where TExtension : IBootstrappingExtension
    {
        public void Initialize(IBootstrappingStrategy<TExtension> strategy)
        {
            Contract.Requires<ArgumentNullException>(strategy != null, "strategy could not be null.");
        }

        public void Run()
        {
            if (Started != null)
                Started(this, new EventArgs());
        }

        public void Shutdown()
        {
        }

        public void Dispose()
        {
        }


        public void Configure()
        {
        }

        public void AddExtension(TExtension extension)
        {
        }


        public event EventHandler Started;
    }
}
